// 埋点模块
class dataTrack {
  constructor(ctx) {
    ctx = ctx || {};
    if (!ctx || typeof ctx._cloud != 'object') {
      throw new Error('初始化用户访问模块时，请传入小程序实例化后的cloud对象');
    }

    // 系统参数
    this._mfutil = ctx._that; // mfutil
    this._cloud = ctx._cloud; // 小程序cloud对象 必传
    this._emitter = ctx._emitter || ''; // 发送消息对象

    // 埋点默认参数
    this._version = ctx.version || 'v3'; // 埋点的版本
    this._platform = ctx.platform || 'Taobao'; // 平台
    this._userid = ''; // 用户的唯一标识符 淘宝侧 使用 mixnick
    this._usernick = ''; // 用户授权之后的明文昵称
    this._usermember = '-1'; // 调用接口获取到的会员等级 -1 表示没有查询 0 表示不是会员 其他表示会员等级
    this._device = this._mfutil.mobileInfo.platform + '_' + this._mfutil.mobileInfo.brand + '_' + this._mfutil.mobileInfo.model;    //  用户当前使用的设备信息
    this._channel = ctx.channel || 'livecard';  //渠道
    this._traceId = new Date().getTime() + ''; // 用户本次访问的唯一标识时间戳
    this._code = ctx.code || '179'; // 埋点code
    this._current_page_name = ''; // 当前页面名称
    this._app_into_time = 0; // 应用进入的时间
    this._open_default_into = ctx.open_default_into === undefined ? true : ctx.open_default_into; // 打开默认的框架APP进入/退出埋点

    // 埋点的服务类型 服务端是云函数 、 云应用
    this._cloud_type = 'cloud_fun';  //云服务类型 cloud_fun :云函数   其他：云应用 cloud_application

    // 云函数参数
    this._cloud_fun_name = ctx.cloud_fun_name || 'dataTrackCloud';
    this._cloud_fun_handler = ctx.cloud_fun_handler || 'custom'; // 云函数公共表 custom 白名单 
    // 云函数数据透出方案 白名单 、 公共表
    this._buried_point_model = ctx.buried_point_model || 'common_table'; // 埋点模式默认为 公共表 common_table 白名单 white_domain
    // 白名单透出模式 直接调用接口透出、数据库保存定时任务
    this._need_timing_task = ctx.need_timing_task === undefined ? false : ctx.need_timing_task;  //是否开启定时任务存储埋点信息
    // 直接调用接口透出参数
    this._white_domain = ctx.white_domain || 'https://go-tracking-kafka.morefun.me'; // 白名单域名  生产环境
    // this._white_domain = ctx.white_domain || 'https://go-tracking-mq-gateway.morefun.me'; // 白名单域名   测试环境
    this._white_path = ctx.white_path || '/go-tracking-mq-gateway/api/v2.1/tracking/rocket/tcp/producer/str'; // 白名单path 单条埋点
    // this._white_path = ctx.white_path || '/go-tracking-mq-gateway/api/v2.1/tracking/rocket/tcp/producer/miniapp/batch'; // 白名单path 多条埋点

    // 云应用
    this._path = '/api/v1/buriedpoint';  //path
    this._method = 'POST';
    this._headers = { 'content-type': 'application/json' };
    //对于一个小程序关联多个云应用的场景，调用非默认云应用，需要指定对应的云应用Id,超时时间单位ms
    this._exts = { 'timeout': 1000 };

    // 埋点前置处理
    // 框架默认的前置数据处理是：获取用户的会员等级，如果出现性能问题的话，就关闭掉（但是需要注意在用户模块你也需要开启获取用户会员等级）
    // 如果需要添加其他前置处理请自己实现
    this._preposition_manage = ctx.preposition_manage === undefined ? true : ctx.preposition_manage; // 是否需要开启前置数据处理
    this._preposition_manage_state = false; // 是否已经完成前置处理
    this._preposition_manage_style = ctx.preposition_manage_style || 'default'; // 前置数据处理模式 默认的 default 特定的 specific
  }

  // 小部件 基础埋点
  async onAppInit(options) {
    // 判断options是否包含渠道
    if (options && options.query && options.query.channel) {
      this._channel = options.query.channel;
    }
    // 监听用户会员状态发生改变的操作
    this._emitter.on("changeMemberState", member => {
      this._usermember = member
    });
    // 应用基础埋点
    this.pvuv();
  }

  // 小部件出现
  async onAppear() {
    if (this._open_default_into) {
      this._app_into_time = new Date().getTime();
      this.operation('into');
    }
  }
  // 小部件消失
  async onDisAppear() {
    if (this._open_default_into) {
      this.timeOnSite(new Date().getTime() - this._app_into_time);
      this.operation('exit');
    }
  }
  // 增加手动触发 app 进入和有效跳出的事件
  // 手动触发 app into
  async onAppInTo() {
    if (!this._open_default_into) {
      this._app_into_time = new Date().getTime();
      this.operation('into');
    }
  }
  // 手动触发 app exit
  async onAppExit() {
    if (!this._open_default_into && this._app_into_time) {
      this.timeOnSite(new Date().getTime() - this._app_into_time);
      this.operation('exit');
    }
  }
  // 授权
  async onAuthorizate(options) {
    // 设置用户头像和昵称
    const { nickName = '' } = options;
    this._usernick = nickName;

  }
  // 数据前置处理
  async prepositionManage() {
    if (this._preposition_manage && !this._preposition_manage_state) {
      if (this._preposition_manage_style === 'default') {
        await this.defaultPrepositionManage();
      } else if (this._preposition_manage_style === 'specific') {
        await this.specificPrepositionManage();
      } else {
        this._preposition_manage_state = true;
      }
    }
  }

  // 框架默认的前置处理,获取用户的会员等级数据
  async defaultPrepositionManage() {
    // console.log('框架默认的埋点前置处理');
    return new Promise(async (resolve, reject) => {
      // 第一次获取并判断
      if (this._mfutil.userAccess && this._mfutil.userAccess.getCacheUserInfo) {
        // 循环处理，如果处理3次之后没有反应,就不进行处理
        let time_number = 0;
        let intTime = setInterval(async () => {
          if (this._preposition_manage_state) {
            clearInterval(intTime);
            resolve();
          } else {
            // 获取用户信息并等待用户会员信息返回
            const oncomingUserMember = await this._mfutil.userAccess.getOncomingUserMemberInfo();
            if (oncomingUserMember) {
              // 判断会员信息进行赋值操作
              const member = oncomingUserMember.member;
              if (member !== undefined && member !== null && (+member >= 0)) {
                this._usermember = oncomingUserMember.member;
              }
              this._preposition_manage_state = true;
              clearInterval(intTime);
              resolve();
            } else {
              time_number += 1;
              if (time_number >= 3) {
                this._preposition_manage_state = true;
                clearInterval(intTime);
                console.log('%c dataTrack 模块 框架默认的埋点前置处理异常(框架的默认前置处理需要打开用户模块的“会员查询”,还需要确认会员查询权限.如果不需要请关闭埋点前置处理)!', 'color: red');
                resolve();
              }
            }
          }
        }, 500);
      } else {
        this._preposition_manage_state = true;
        console.log('%c dataTrack 模块 框架默认的埋点前置处理获取对象异常!', 'color: red');
        resolve();
      }
    })
  }

  // 特定的前置处理
  async specificPrepositionManage() {
    // 可以发送请求,前置处理数据
    this._preposition_manage_state = true;
  }

  // pvuv埋点
  async pvuv() {
    await this.prepositionManage();
    const params = {
      version: this._version,
      traceId: this._traceId,
      projectCode: this._code,
      platform: this._platform,
      channel: this._channel,
      device: this._device,
      timestamp: new Date().getTime() + '',
      province: '',
      city: '',
      location: {
        ip: ''
      },
      userId: this._userid,
      userData: {
        plainTextNick: this._usernick,
        member: this._usermember,
      },
      page: '',
      type: 'flowSource',
      customType: '',
      value: ''
    }
    return await this.trackingRequest(params);
  }

  // 自定义埋点
  async custom(customType, value = '', pageName = '') {
    if (!customType) {
      console.log('%c  自定义埋点--请传入自定义埋点信息！', 'color: red');
      return;
    }
    await this.prepositionManage();
    const params = {
      version: this._version,
      traceId: this._traceId,
      projectCode: this._code,
      platform: this._platform,
      channel: this._channel,
      device: this._device,
      timestamp: new Date().getTime() + '',
      province: '',
      city: '',
      location: {
        ip: ''
      },
      userId: this._userid,
      userData: {
        plainTextNick: this._usernick,
        member: this._usermember,
      },
      customType: customType + '',
      value: value + '',
      page: pageName || this._current_page_name,
      type: '',
    }
    return await this.trackingRequest(params);
  }

  // 页面操作埋点
  async operation(type, page = '') {
    await this.prepositionManage();
    // 设置当前页面的名称,进入那个页面，页面名称就是啥
    if (type === 'into') this._current_page_name = page;
    const params = {
      version: this._version,
      traceId: this._traceId,
      projectCode: this._code,
      platform: this._platform,
      channel: this._channel,
      device: this._device,
      timestamp: new Date().getTime() + '',
      province: '',
      city: '',
      location: {
        ip: ''
      },
      userId: this._userid,
      userData: {
        plainTextNick: this._usernick,
        member: this._usermember,
      },
      type,
      page: page + '',
      customType: '',
      value: ''
    }
    return await this.trackingRequest(params);
  }
  // 停留时长埋点
  async timeOnSite(value, page = '') {
    await this.prepositionManage();
    const params = {
      version: this._version,
      traceId: this._traceId,
      projectCode: this._code,
      platform: this._platform,
      channel: this._channel,
      device: this._device,
      timestamp: new Date().getTime() + '',
      province: '',
      city: '',
      location: {
        ip: ''
      },
      userId: this._userid,
      userData: {
        plainTextNick: this._usernick,
        member: this._usermember,
      },
      type: 'timeOnSite',
      page,
      value: value + '',
      customType: ''
    }
    return await this.trackingRequest(params);
  }


  // 埋点的数据请求
  async trackingRequest(buried_point_data) {
    if (this._cloud_type === 'cloud_fun') {
      return await this._cloud.function.invoke(this._cloud_fun_name, { buried_point_data, buried_point_model: this._buried_point_model, white_domain: this._white_domain, white_path: this._white_path, needTimingTask: this._need_timing_task }, this._cloud_fun_handler);
    } else {
      // 云应用
      return await this._cloud.application.httpRequest({
        //对于一个小程序关联多个云应用的场景，调用非默认云应用，需要指定对应的云应用Id,超时时间单位ms
        //不需要完整域名，只需要接口访问路径即可
        'path': this._path,
        'method': this._method,
        'headers': this._headers,
        'body': { buried_point_data },
        //对于一个小程序关联多个云应用的场景，调用非默认云应用，需要指定对应的云应用Id,超时时间单位ms
        'exts': this._exts
      });
    }
  }

  // 发送请求 默认为云函数
  async request(obj, type = 'cloud') {
    // 判断 userAccess 模块的云函数请求是否存在异常
    if (typeof this._cloud != 'object') {
      console.log('%c userAccess 模块的云函数请求存在异常!', 'color: red');
      return;
    } else {
      if (type === 'cloud') {
        return await this._cloud.function.invoke(obj.name, obj.params, obj.handler);
      } else {
        return await this._cloud.application.httpRequest({
          'path': obj.path,
          'method': obj.method,
          'headers': obj.headers,
          'params': obj.params,
          'body': obj.body,
          'exts': obj.exts
        });
      }
    }
  }

}

module.exports = exports.dataTrack = dataTrack;